﻿#region License

// PentaBiz - Sustainable Software Development Framework Copyright (C) 2013 Zoltán Csizmazia
// 
// This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace PentaBiz.WpfTools.Reflection
{
    public static class ReflectionExtensions
    {
        public static bool IsInlineDelegate(this Delegate @delegate)
        {
            return @delegate.Target == null;
        }

        public static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>(this PropertyInfo propertyInfo)
            where TAttribute : Attribute
        {
            return propertyInfo.GetCustomAttributes(typeof (TAttribute), true).OfType<TAttribute>();
        }

        public static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>(this MemberInfo memberInfo)
            where TAttribute : Attribute
        {
            return memberInfo.GetCustomAttributes(typeof (TAttribute), true).OfType<TAttribute>();
        }

        /// <summary>
        ///     [1]
        ///     Given a lambda expression of a Property, return the PropertyInfo for the property.
        ///     http://codebetter.com/blogs/patricksmacchia/archive/2010/06/28/elegant-infoof-operators-in-c-read-info-of.aspx
        /// </summary>
        /// <typeparam name="T">Property type</typeparam>
        /// <param name="expression">Lambda expression</param>
        /// <returns>PropertyInfo for property</returns>
        public static PropertyInfo PropertyOf<T>(Expression<Func<T>> expression)
        {
            MemberExpression body = (MemberExpression) expression.Body;
            return (PropertyInfo) body.Member;
        }

        /// <summary>
        ///     [3]
        ///     From http://stackoverflow.com/questions/491429/how-to-get-the-propertyinfo-of-a-specific-property
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public static class PropertyHelper<T>
        {
            public static PropertyInfo GetProperty<TValue>(
                Expression<Func<T, TValue>> selector)
            {
                Expression body = selector;
                if (body is LambdaExpression)
                {
                    body = ((LambdaExpression) body).Body;
                }
                switch (body.NodeType)
                {
                    case ExpressionType.MemberAccess:
                        return (PropertyInfo) ((MemberExpression) body).Member;
                    default:
                        throw new InvalidOperationException();
                }
            }
        }
    }
}